package com.tongle.frs.common.util.email;

import com.tongle.frs.common.log.HiwiLog;
import com.tongle.frs.common.log.HiwiLogFactory;
import javax.mail.*;
import javax.mail.Flags.Flag;
import javax.mail.Message.RecipientType;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;

public class ReceiveMailUtils
{
  private static HiwiLog logger = HiwiLogFactory.getLogger(ReceiveMailUtils.class);

  private MimeMessage mimeMessage = null;
  private String saveAttachPath = "";
  private StringBuffer bodyText = new StringBuffer();
  private String dateFormat = "yy-MM-dd HH:mm";

  public ReceiveMailUtils()
  {
  }

  public ReceiveMailUtils(MimeMessage mimeMessage)
  {
    this.mimeMessage = mimeMessage;
    logger.info("创建一个ReceiveEmail对象....");
  }

  public void setMimeMessage(MimeMessage mimeMessage) {
    this.mimeMessage = mimeMessage;
    logger.info("设置一个MimeMessage对象...");
  }

  public String getFrom()
    throws Exception
  {
    InternetAddress[] address = (InternetAddress[])(InternetAddress[])this.mimeMessage.getFrom();
    String from = address[0].getAddress();
    if (from == null) {
      from = "";
      logger.info("无法知道发送者.");
    }

    return from;
  }

  public String getMailAddress(String type)
    throws Exception
  {
    String mailAddr = "";
    String addType = type.toUpperCase();

    InternetAddress[] address = null;
    if ((addType.equals("TO")) || (addType.equals("CC")) || (addType.equals("BCC")))
    {
      if (addType.equals("TO"))
      {
        address = (InternetAddress[])(InternetAddress[])this.mimeMessage
          .getRecipients(RecipientType.TO);
      }
      else if (addType.equals("CC"))
      {
        address = (InternetAddress[])(InternetAddress[])this.mimeMessage
          .getRecipients(RecipientType.CC);
      }
      else
      {
        address = (InternetAddress[])(InternetAddress[])this.mimeMessage
          .getRecipients(RecipientType.BCC);
      }

      if (address != null) {
        for (int i = 0; i < address.length; i++) {
          String emailAddr = address[i].getAddress();
          if (emailAddr == null) {
            emailAddr = "";
          } else {
            logger.info("转换之前的emailAddr: " + emailAddr);
            emailAddr = MimeUtility.decodeText(emailAddr);
            logger.info("转换之后的emailAddr: " + emailAddr);
          }
          String personal = address[i].getPersonal();
          if (personal == null) {
            personal = "";
          } else {
            logger.info("转换之前的personal: " + personal);
            personal = MimeUtility.decodeText(personal);
            logger.info("转换之后的personal: " + personal);
          }
          String compositeto = personal + "<" + emailAddr + ">";
          logger.info("完整的邮件地址：" + compositeto);
          mailAddr = mailAddr + "," + compositeto;
        }
        mailAddr = mailAddr.substring(1);
      }
    } else {
      throw new Exception("错误的电子邮件类型!");
    }
    return mailAddr;
  }

  public String getSubject()
    throws MessagingException
  {
    String subject = "";
    try {
      logger.info("转换前的subject：" + this.mimeMessage.getSubject());
      subject = MimeUtility.decodeText(this.mimeMessage.getSubject());
      logger.info("转换后的subject: " + this.mimeMessage.getSubject());
      if (subject == null)
        subject = "";
    }
    catch (Exception exce) {
      exce.printStackTrace();
    }
    return subject;
  }

  public String getSentDate()
    throws Exception
  {
    Date sentDate = this.mimeMessage.getSentDate();
    logger.info("发送日期 原始类型: " + this.dateFormat);
    SimpleDateFormat format = new SimpleDateFormat(this.dateFormat);
    String strSentDate = format.format(sentDate);
    logger.info("发送日期 可读类型: " + strSentDate);
    return strSentDate;
  }

  public String getBodyText()
  {
    return this.bodyText.toString();
  }

  public void getMailContent(Part part)
    throws Exception
  {
    String contentType = part.getContentType();

    logger.info("邮件的MimeType类型: " + contentType);

    int nameIndex = contentType.indexOf("name");

    boolean conName = false;

    if (nameIndex != -1) {
      conName = true;
    }

    logger.info("邮件内容的类型:　" + contentType);

    if ((part.isMimeType("text/plain")) && (!conName))
    {
      this.bodyText.append((String)part.getContent());
    } else if ((part.isMimeType("text/html")) && (!conName))
    {
      this.bodyText.append((String)part.getContent());
    } else if (part.isMimeType("multipart/*"))
    {
      Multipart multipart = (Multipart)part.getContent();
      int counts = multipart.getCount();
      for (int i = 0; i < counts; i++)
        getMailContent(multipart.getBodyPart(i));
    }
    else if (part.isMimeType("message/rfc822"))
    {
      getMailContent((Part)part.getContent());
    }
  }

  public boolean getReplySign()
    throws MessagingException
  {
    boolean replySign = false;

    String[] needReply = this.mimeMessage.getHeader("Disposition-Notification-To");

    if (needReply != null) {
      replySign = true;
    }
    if (replySign)
      logger.info("该邮件需要回复");
    else {
      logger.info("该邮件不需要回复");
    }
    return replySign;
  }

  public String getMessageId()
    throws MessagingException
  {
    String messageID = this.mimeMessage.getMessageID();
    logger.info("邮件ID: " + messageID);
    return messageID;
  }

  public boolean isNew()
    throws MessagingException
  {
    boolean isNew = false;
    Flags flags = this.mimeMessage.getFlags();
    Flag[] flag = flags.getSystemFlags();
    logger.info("flags的长度:　" + flag.length);
    for (int i = 0; i < flag.length; i++) {
      if (flag[i] == Flag.SEEN) {
        isNew = true;
        logger.info("seen email...");
      }
    }

    return isNew;
  }

  public boolean isContainAttach(Part part)
    throws Exception
  {
    boolean attachFlag = false;

    if (part.isMimeType("multipart/*")) {
      Multipart mp = (Multipart)part.getContent();
      for (int i = 0; i < mp.getCount(); i++) {
        BodyPart mPart = mp.getBodyPart(i);
        String disposition = mPart.getDisposition();
        if ((disposition != null) && (
          (disposition
          .equals("attachment")) || 
          (disposition
          .equals("inline"))))
        {
          attachFlag = true;
        } else if (mPart.isMimeType("multipart/*")) {
          attachFlag = isContainAttach(mPart);
        } else {
          String conType = mPart.getContentType();

          if (conType.toLowerCase().indexOf("application") != -1)
            attachFlag = true;
          if (conType.toLowerCase().indexOf("name") != -1)
            attachFlag = true;
        }
      }
    } else if (part.isMimeType("message/rfc822")) {
      attachFlag = isContainAttach((Part)part.getContent());
    }
    return attachFlag;
  }

  public void saveAttachMent(Part part)
    throws Exception
  {
    String fileName = "";
    if (part.isMimeType("multipart/*")) {
      Multipart mp = (Multipart)part.getContent();
      for (int i = 0; i < mp.getCount(); i++) {
        BodyPart mPart = mp.getBodyPart(i);
        String disposition = mPart.getDisposition();
        if ((disposition != null) && (
          (disposition
          .equals("attachment")) || 
          (disposition
          .equals("inline"))))
        {
          fileName = mPart.getFileName();
          if (fileName.toLowerCase().indexOf("gb2312") != -1) {
            fileName = MimeUtility.decodeText(fileName);
          }
          saveFile(fileName, mPart.getInputStream());
        } else if (mPart.isMimeType("multipart/*")) {
          saveAttachMent(mPart);
        } else {
          fileName = mPart.getFileName();
          if ((fileName == null) || 
            (fileName
            .toLowerCase().indexOf("GB2312") == -1)) continue;
          fileName = MimeUtility.decodeText(fileName);
          saveFile(fileName, mPart.getInputStream());
        }
      }
    }
    else if (part.isMimeType("message/rfc822")) {
      saveAttachMent((Part)part.getContent());
    }
  }

  public void setAttachPath(String attachPath)
  {
    this.saveAttachPath = attachPath;
  }

  public void setDateFormat(String format)
    throws Exception
  {
    this.dateFormat = format;
  }

  public String getAttachPath()
  {
    return this.saveAttachPath;
  }

  private void saveFile(String fileName, InputStream in)
    throws Exception
  {
    String osName = System.getProperty("os.name");
    String storeDir = getAttachPath();
    String separator = "";
    if (osName == null) {
      osName = "";
    }
    if (osName.toLowerCase().indexOf("win") != -1) {
      separator = "\\";
      if ((storeDir == null) || (storeDir.equals("")))
        storeDir = "c:\\tmp";
    } else {
      separator = "/";
      storeDir = "/tmp";
    }
    File storeFile = new File(storeDir + separator + fileName);
    logger.info("附件的保存地址:　" + storeFile.toString());

    BufferedOutputStream bos = null;
    BufferedInputStream bis = null;
    try
    {
      bos = new BufferedOutputStream(new FileOutputStream(storeFile));
      bis = new BufferedInputStream(in);
      int c;
      while ((c = bis.read()) != -1) {
        bos.write(c);
        bos.flush();
      }
    } catch (Exception exception) {
      exception.printStackTrace();
      throw new Exception("文件保存失败!");
    } finally {
      bos.close();
      bis.close();
    }
  }

  public static String receiveMail(String account, String password) {
    Properties props = new Properties();
    Session session = Session.getDefaultInstance(props, null);
    try {
      String host = account.split("@")[1];
      host = "pop." + host;
      Store store = session.getStore("pop3");
      store.connect(host, account, password);
      Folder folder = store.getFolder("INBOX");
      folder.open(1);
      Message[] message = folder.getMessages(folder.getMessageCount(), folder
        .getMessageCount());
      ReceiveMailUtils re = null;
      if (message.length > 0) {
        re = new ReceiveMailUtils((MimeMessage)message[0]);
        logger.info("接收邮件　发送人地址:　" + re.getFrom());
        return re.getFrom();
      }
    } catch (Exception e) {
      logger.error("接收邮件异常", e);
    }
    return "";
  }

  public static void main(String[] args)
    throws Exception
  {
    String host = "pop.163.com";
    String username = "eyuntx_server@163.com";
    String password = "qtvvpkqkksitlwpe";

    Properties props = new Properties();
    Session session = Session.getDefaultInstance(props, null);

    Store store = session.getStore("pop3");
    store.connect(host, username, password);

    Folder folder = store.getFolder("INBOX");
    folder.open(1);
    Message[] message = folder.getMessages(folder.getMessageCount(), folder
      .getMessageCount());
    logger.info("邮件数量:　" + message.length);
    ReceiveMailUtils re = null;

    for (int i = 0; i < message.length; i++) {
      re = new ReceiveMailUtils((MimeMessage)message[i]);
      logger.info("邮件　" + i + "　主题:　" + re.getSubject());
      logger.info("邮件　" + i + "　发送时间:　" + re.getSentDate());
      logger.info("邮件　" + i + "　是否需要回复:　" + re.getReplySign());
      logger.info("邮件　" + i + "　是否已读:　" + re.isNew());
      logger.info("邮件　" + i + "　是否包含附件:　" + re
        .isContainAttach(message[i]));

      logger.info("邮件　" + i + "　发送人地址:　" + re.getFrom());
      logger.info("邮件　" + i + "　收信人地址:　" + re.getMailAddress("to"));
      logger.info("邮件　" + i + "　抄送:　" + re.getMailAddress("cc"));
      logger.info("邮件　" + i + "　暗抄:　" + re.getMailAddress("bcc"));
      re.setDateFormat("yy年MM月dd日　HH:mm");
      logger.info("邮件　" + i + "　发送时间:　" + re.getSentDate());
      logger.info("邮件　" + i + "　邮件ID:　" + re.getMessageId());
      re.getMailContent(message[i]);
      logger.info("邮件　" + i + "　正文内容:　\r\n" + re.getBodyText());
      re.setAttachPath("e:\\");
      re.saveAttachMent(message[i]);
    }
  }
}